added Feb 2001 SDK
[windows-sources.git] / shared source / sscli20 / jscript / engine / arrayprototype.cs
blobc5f07bf4ca9e0cd611f43bba2060d57d2041efe3
1 // ==++==
2 //
3 //
4 // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
5 //
6 // The use and distribution terms for this software are contained in the file
7 // named license.txt, which can be found in the root of this distribution.
8 // By using this software in any fashion, you are agreeing to be bound by the
9 // terms of this license.
10 //
11 // You must not remove this notice, or any other, from this software.
12 //
13 //
14 // ==--==
16 namespace Microsoft.JScript {
18 using Microsoft.JScript.Vsa;
19 using System;
20 using System.Reflection;
21 using System.Text;
23 public class ArrayPrototype : ArrayObject{
24 internal static readonly ArrayPrototype ob = new ArrayPrototype(ObjectPrototype.ob);
25 internal static ArrayConstructor _constructor;
27 internal ArrayPrototype(ObjectPrototype parent)
28 : base(parent) {
29 this.noExpando = true;
32 [JSFunctionAttribute(JSFunctionAttributeEnum.HasThisObject|JSFunctionAttributeEnum.HasVarArgs|JSFunctionAttributeEnum.HasEngine, JSBuiltin.Array_concat)]
33 public static ArrayObject concat(Object thisob, VsaEngine engine, params Object[] args){
34 ArrayObject arrayObj = engine.GetOriginalArrayConstructor().Construct();
35 if (thisob is ArrayObject)
36 arrayObj.Concat((ArrayObject)thisob);
37 else
38 arrayObj.Concat(thisob);
39 for (int i = 0; i < args.Length; i++){
40 Object arg = args[i];
41 if (arg is ArrayObject)
42 arrayObj.Concat((ArrayObject)arg);
43 else
44 arrayObj.Concat(arg);
46 return arrayObj;
49 public static ArrayConstructor constructor{
50 get{
51 return ArrayPrototype._constructor;
55 [JSFunctionAttribute(JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Array_join)]
56 public static String join(Object thisob, Object separator){
57 if (separator is Missing)
58 return Join(thisob, ",", false);
59 else
60 return Join(thisob, Convert.ToString(separator), false);
63 internal static String Join(Object thisob, String separator, bool localize){
64 StringBuilder str = new StringBuilder();
65 uint thisLength = Convert.ToUint32(LateBinding.GetMemberValue(thisob, "length"));
66 if (thisLength > int.MaxValue)
67 throw new JScriptException(JSError.OutOfMemory);
68 // Small optimization so we're not doing a bunch of reallocs for large arrays.
69 if (thisLength > str.Capacity)
70 str.Capacity = (int)thisLength;
71 for (uint i = 0; i < thisLength; i++){
72 Object value = LateBinding.GetValueAtIndex(thisob, i);
73 if (value != null && !(value is Missing)){
74 if (localize)
75 str.Append(Convert.ToLocaleString(value));
76 else
77 str.Append(Convert.ToString(value));
79 if (i < thisLength-1)
80 str.Append(separator);
82 return str.ToString();
85 [JSFunctionAttribute(JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Array_pop)]
86 public static Object pop(Object thisob){
87 uint thisLength = Convert.ToUint32(LateBinding.GetMemberValue(thisob, "length"));
88 if (thisLength == 0){
89 LateBinding.SetMemberValue(thisob, "length", 0);
90 return null;
92 Object result = LateBinding.GetValueAtIndex(thisob, thisLength-1);
93 LateBinding.DeleteValueAtIndex(thisob, thisLength-1);
94 LateBinding.SetMemberValue(thisob, "length", thisLength-1);
95 return result;
98 [JSFunctionAttribute(JSFunctionAttributeEnum.HasThisObject|JSFunctionAttributeEnum.HasVarArgs, JSBuiltin.Array_push)]
99 public static long push(Object thisob, params Object[] args){
100 uint length = Convert.ToUint32(LateBinding.GetMemberValue(thisob, "length"));
101 for (uint i = 0; i < args.Length; i++)
102 LateBinding.SetValueAtIndex(thisob, i+(ulong)length, args[i]);
103 long newLength = length+args.Length;
104 LateBinding.SetMemberValue(thisob, "length", newLength);
105 return newLength;
108 [JSFunctionAttribute(JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Array_reverse)]
109 public static Object reverse(Object thisob){
110 uint thisLength = Convert.ToUint32(LateBinding.GetMemberValue(thisob, "length"));
111 uint halfSize = thisLength/2;
112 for (uint low = 0, high = thisLength - 1; low < halfSize; low++, high--)
113 LateBinding.SwapValues(thisob, low, high);
114 return thisob;
117 internal override void SetMemberValue(String name, Object value){
118 if (this.noExpando) //This the fast prototype
119 throw new JScriptException(JSError.OLENoPropOrMethod);
120 base.SetMemberValue(name, value);
123 internal override void SetValueAtIndex(uint index, Object value){
124 if (this.noExpando) //This the fast prototype
125 throw new JScriptException(JSError.OLENoPropOrMethod);
126 base.SetValueAtIndex(index, value);
129 [JSFunctionAttribute(JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Array_shift)]
130 public static Object shift(Object thisob){
131 Object res = null;
132 if (thisob is ArrayObject)
133 return ((ArrayObject)thisob).Shift();
134 uint length = Convert.ToUint32(LateBinding.GetMemberValue(thisob, "length"));
135 if (length == 0){
136 LateBinding.SetMemberValue(thisob, "length", 0);
137 return res;
139 res = LateBinding.GetValueAtIndex(thisob, 0);
140 for (uint i = 1; i < length; i++){
141 Object val = LateBinding.GetValueAtIndex(thisob, i);
142 if (val is Missing)
143 LateBinding.DeleteValueAtIndex(thisob, i-1);
144 else
145 LateBinding.SetValueAtIndex(thisob, i-1, val);
147 LateBinding.DeleteValueAtIndex(thisob, length-1);
148 LateBinding.SetMemberValue(thisob, "length", length-1);
149 return res;
152 [JSFunctionAttribute(JSFunctionAttributeEnum.HasThisObject|JSFunctionAttributeEnum.HasEngine, JSBuiltin.Array_slice)]
153 public static ArrayObject slice(Object thisob, VsaEngine engine, double start, Object end){
154 ArrayObject array = engine.GetOriginalArrayConstructor().Construct();
155 uint length = Convert.ToUint32(LateBinding.GetMemberValue(thisob, "length"));
156 // compute the start index
157 long startIndex = Runtime.DoubleToInt64(Convert.ToInteger(start));
158 if (startIndex < 0){
159 startIndex = length + startIndex;
160 if (startIndex < 0)
161 startIndex = 0;
162 }else if (startIndex > length)
163 startIndex = length;
164 // compute the end index
165 long endIndex = length;
166 if (end != null && !(end is Missing)){
167 endIndex = Runtime.DoubleToInt64(Convert.ToInteger(end));
168 if (endIndex < 0){
169 endIndex = length + endIndex;
170 if (endIndex < 0)
171 endIndex = 0;
172 }else if (endIndex > length)
173 endIndex = length;
175 // slice
176 if (endIndex > startIndex){
177 array.length = endIndex - startIndex;
178 for (ulong i = (ulong)startIndex, j = 0; i < (ulong)endIndex; i++, j++){
179 Object val = LateBinding.GetValueAtIndex(thisob, i);
180 if (!(val is Missing))
181 LateBinding.SetValueAtIndex(array, j, val);
184 return array;
187 [JSFunctionAttribute(JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Array_sort)]
188 public static Object sort(Object thisob, Object function){
189 ScriptFunction func = null;
190 if (function is ScriptFunction)
191 func = (ScriptFunction)function;
192 uint length = Convert.ToUint32(LateBinding.GetMemberValue(thisob, "length"));
193 if (thisob is ArrayObject)
194 ((ArrayObject)thisob).Sort(func);
195 else if (length <= Int32.MaxValue){
196 QuickSort qs = new QuickSort(thisob, func);
197 qs.SortObject(0, length);
199 return thisob;
202 [JSFunctionAttribute(JSFunctionAttributeEnum.HasThisObject|JSFunctionAttributeEnum.HasVarArgs|JSFunctionAttributeEnum.HasEngine, JSBuiltin.Array_splice)]
203 public static ArrayObject splice(Object thisob, VsaEngine engine, double start, double deleteCnt, params Object[] args){
204 uint oldLength = Convert.ToUint32(LateBinding.GetMemberValue(thisob, "length"));
205 // compute the start index
206 long startIndex = Runtime.DoubleToInt64(Convert.ToInteger(start));
207 if (startIndex < 0){
208 startIndex = oldLength + startIndex;
209 if (startIndex < 0)
210 startIndex = 0;
211 }else if (startIndex > oldLength)
212 startIndex = oldLength;
214 // compute the number of items to delete
215 long deleteCount = Runtime.DoubleToInt64(Convert.ToInteger(deleteCnt));
216 if (deleteCount < 0)
217 deleteCount = 0;
218 else if (deleteCount > oldLength - startIndex)
219 deleteCount = oldLength - startIndex;
220 long newLength = oldLength + args.Length - deleteCount;
222 // create an array for the result
223 ArrayObject result = engine.GetOriginalArrayConstructor().Construct();
224 result.length = deleteCount;
226 // special case array objects (nice speedup if dense)
227 if (thisob is ArrayObject){
228 ((ArrayObject)thisob).Splice((uint)startIndex, (uint)deleteCount, args, result, (uint)oldLength, (uint)newLength);
229 return result;
232 // copy the deleted items to the result array
233 for (ulong i = 0; i < (ulong)deleteCount; i++)
234 result.SetValueAtIndex((uint)i, LateBinding.GetValueAtIndex(thisob, i+(ulong)startIndex));
236 // shift the remaining elements left or right
237 long n = oldLength-startIndex-deleteCount;
238 if (newLength < oldLength){
239 for (long i = 0; i < n; i++)
240 LateBinding.SetValueAtIndex(thisob, (ulong)(i+startIndex+args.Length), LateBinding.GetValueAtIndex(thisob, (ulong)(i+startIndex+deleteCount)));
241 LateBinding.SetMemberValue(thisob, "length", newLength);
242 }else{
243 LateBinding.SetMemberValue(thisob, "length", newLength);
244 for (long i = n-1; i >= 0; i--)
245 LateBinding.SetValueAtIndex(thisob, (ulong)(i+startIndex+args.Length), LateBinding.GetValueAtIndex(thisob, (ulong)(i+startIndex+deleteCount)));
248 // splice in the arguments
249 int m = args == null ? 0 : args.Length;
250 for (uint i = 0; i < m; i++)
251 LateBinding.SetValueAtIndex(thisob, i+(ulong)startIndex, args[i]);
253 return result;
256 [JSFunctionAttribute(JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Array_toLocaleString)]
257 public static String toLocaleString(Object thisob){
258 if (thisob is ArrayObject){
259 StringBuilder sep = new StringBuilder(System.Globalization.CultureInfo.CurrentCulture.TextInfo.ListSeparator);
260 if (sep[sep.Length-1] != ' ')
261 sep.Append(' ');
262 return ArrayPrototype.Join(thisob, sep.ToString(), true);
264 throw new JScriptException(JSError.NeedArrayObject);
267 [JSFunctionAttribute(JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Array_toString)]
268 public static String toString(Object thisob){
269 if (thisob is ArrayObject)
270 return ArrayPrototype.Join(thisob, ",", false);
271 throw new JScriptException(JSError.NeedArrayObject);
274 [JSFunctionAttribute(JSFunctionAttributeEnum.HasThisObject|JSFunctionAttributeEnum.HasVarArgs, JSBuiltin.Array_unshift)]
275 public static Object unshift(Object thisob, params Object[] args){
276 if (args == null || args.Length == 0) return thisob;
277 if (thisob is ArrayObject)
278 return ((ArrayObject)thisob).Unshift(args);
279 uint oldLength = Convert.ToUint32(LateBinding.GetMemberValue(thisob, "length"));
280 long newLength = oldLength + args.Length;
281 LateBinding.SetMemberValue(thisob, "length", newLength);
282 // shift the array
283 for (long i = oldLength - 1; i >= 0; i--){
284 Object val = LateBinding.GetValueAtIndex(thisob, (ulong)i);
285 if (val is Missing)
286 LateBinding.DeleteValueAtIndex(thisob, (ulong)(i + args.Length));
287 else
288 LateBinding.SetValueAtIndex(thisob, (ulong)(i + args.Length), val);
290 // copy the input args
291 for (uint i = 0; i < args.Length; i++)
292 LateBinding.SetValueAtIndex(thisob, i, args[i]);
293 return thisob;